/**
 * Program   :   MyInvocationSecurityMetadataSourceService.java
 * Author    :   shadow guo
 * Create    :   2013-6-9 上午11:10:14
 *
 * Copyright 2008 by Tongfu Information Technology Co. Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Tongfu Information Technology Co. Ltd. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Tongfu Information Technology Co. Ltd.
 * 
 */
package com.tongfusoft.web.core.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;

import com.tongfusoft.web.core.data.PrivilegeData;
import com.tongfusoft.web.core.data.ResourceData;
import com.tongfusoft.web.core.service.ISecurityService;

/**
 * 最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。
 * 此类在初始化时，应该取到所有资源及其对应角色的定义。
 * 
 */
public class InvocationSecurityMetadataSourceService implements
		FilterInvocationSecurityMetadataSource {
	
	private ISecurityService securityService;
	
	private UrlMatcher urlMatcher = new AntUrlPathMatcher();

	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	public ISecurityService getSecurityService() {
		return securityService;
	}

	public void setSecurityService(ISecurityService securityService) {
		this.securityService = securityService;
	}

	

	public InvocationSecurityMetadataSourceService(ISecurityService _securityService) {
		this.securityService = _securityService;
		loadResourceDefine();
	}

	private void loadResourceDefine() {
		/*
		 * 应当是资源为key， 权限为value。 资源通常为url，
		 * 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
		 */
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();

		// 在Web服务器启动时，提取系统中的所有权限。
		List<PrivilegeData> privilegeList = this.getSecurityService().getAllPrivilege();
		for(PrivilegeData privilege : privilegeList){
			ConfigAttribute ca = new SecurityConfig(privilege.getPrivilegeName());
			
			//TODO 此处的循环次数太多，需要改进
			List<ResourceData> resList = this.getSecurityService().getResroucesByPrivilege(privilege);
			
			/*
			 * 判断资源文件和权限的对应关系，如果已经存在相关的资源主体，
			 * 则要通过该主体为key提取出权限集合，将权限增加到权限集合中。
			 */
			for(ResourceData res : resList){
				if(resourceMap.containsKey(res.getResourceContent())){
					resourceMap.get(res.getResourceContent()).add(ca);
				}else{
					Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
					atts.add(ca);
					resourceMap.put(res.getResourceContent(), atts);
				}
			}
		}
	}

	@Override
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		// 根据URL，找到相关的权限配置。
		// object 是一个URL，被用户请求的url。
		String url = ((FilterInvocation) object).getRequestUrl();

		int firstQuestionMarkIndex = url.indexOf("?");

		if (firstQuestionMarkIndex != -1) {
			url = url.substring(0, firstQuestionMarkIndex);
		}

		Iterator<String> ite = resourceMap.keySet().iterator();

		while (ite.hasNext()) {
			String resURL = ite.next();

			if (urlMatcher.pathMatchesUrl(url, resURL)) {
				return resourceMap.get(resURL);
			}
		}

		return null;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

}
